import time
import logging
from typing import Dict, Any, List, Optional
from datetime import datetime

# 导入子模块
from .cloud_simulator import CloudSimulator, SimulationResult
from .smart_router import SmartRouter, Order
from .position_sizer import PositionSizer, SizingMethod
from .execution_strategy import ExecutionStrategy, ExecutionType

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger('AutoOrderEngine')

class RuleDSL:
    """策略规则解释器"""
    def __init__(self):
        self.rules = []
        self.rule_id_counter = 0
        logger.info("RuleDSL initialized")
    
    def add_rule(self, rule_definition: Dict[str, Any]) -> int:
        """添加策略规则"""
        # 为规则分配ID
        rule_id = self.rule_id_counter
        self.rule_id_counter += 1
        
        # 添加规则
        rule = rule_definition.copy()
        rule['rule_id'] = rule_id
        rule['created_at'] = time.time()
        rule['last_triggered'] = None
        rule['trigger_count'] = 0
        
        self.rules.append(rule)
        
        logger.info(f"Rule added: {rule_id}, definition: {rule_definition}")
        return rule_id
    
    def remove_rule(self, rule_id: int) -> bool:
        """移除策略规则"""
        for i, rule in enumerate(self.rules):
            if rule['rule_id'] == rule_id:
                self.rules.pop(i)
                logger.info(f"Rule removed: {rule_id}")
                return True
        
        logger.warning(f"Rule not found: {rule_id}")
        return False
    
    def update_rule(self, rule_id: int, updated_definition: Dict[str, Any]) -> bool:
        """更新策略规则"""
        for i, rule in enumerate(self.rules):
            if rule['rule_id'] == rule_id:
                # 保留规则ID和元数据
                updated_rule = updated_definition.copy()
                updated_rule['rule_id'] = rule_id
                updated_rule['created_at'] = rule['created_at']
                updated_rule['last_triggered'] = rule['last_triggered']
                updated_rule['trigger_count'] = rule['trigger_count']
                
                self.rules[i] = updated_rule
                logger.info(f"Rule updated: {rule_id}, new definition: {updated_definition}")
                return True
        
        logger.warning(f"Rule not found for update: {rule_id}")
        return False
    
    def get_rules(self) -> List[Dict[str, Any]]:
        """获取所有规则"""
        return self.rules.copy()
    
    def check_rules(self, market_data: Dict[str, Any]) -> List[Dict[str, Any]]:
        """检查哪些规则被触发"""
        triggered_rules = []
        current_time = time.time()
        
        for rule in self.rules:
            # 检查是否在禁用状态
            if rule.get('disabled', False):
                continue
            
            # 检查冷却时间
            cooldown_period = rule.get('cooldown_seconds', 60)  # 默认60秒冷却时间
            if rule['last_triggered'] and current_time - rule['last_triggered'] < cooldown_period:
                continue
            
            # 检查规则条件
            if self._evaluate_rule(rule, market_data):
                # 记录触发信息
                rule['last_triggered'] = current_time
                rule['trigger_count'] += 1
                
                # 添加到触发规则列表
                triggered_rules.append(rule.copy())
                
                logger.info(f"Rule triggered: {rule['rule_id']}, symbol: {rule.get('symbol')}")
        
        return triggered_rules
    
    def _evaluate_rule(self, rule: Dict[str, Any], market_data: Dict[str, Any]) -> bool:
        """评估单个规则是否触发"""
        try:
            # 获取规则条件
            conditions = rule.get('conditions', [])
            operator = rule.get('operator', 'ALL')  # ALL 或 ANY
            
            # 如果没有条件，默认不触发
            if not conditions:
                return False
            
            # 评估所有条件
            results = []
            
            for condition in conditions:
                # 提取条件参数
                field = condition.get('field')
                comparator = condition.get('comparator')
                value = condition.get('value')
                
                # 检查市场数据中是否有该字段
                if field not in market_data:
                    results.append(False)
                    continue
                
                # 获取市场数据中的值
                market_value = market_data[field]
                
                # 评估条件
                result = self._compare_values(market_value, comparator, value)
                results.append(result)
            
            # 根据操作符组合结果
            if operator == 'ALL':
                return all(results)
            elif operator == 'ANY':
                return any(results)
            else:
                logger.error(f"Invalid operator: {operator}")
                return False
                
        except Exception as e:
            logger.error(f"Error evaluating rule {rule.get('rule_id')}: {str(e)}")
            return False
    
    def _compare_values(self, market_value: Any, comparator: str, value: Any) -> bool:
        """比较市场值和条件值"""
        try:
            # 确保类型匹配
            if isinstance(market_value, (int, float)) and isinstance(value, (int, float)):
                if comparator == '>':
                    return market_value > value
                elif comparator == '<':
                    return market_value < value
                elif comparator == '>=':
                    return market_value >= value
                elif comparator == '<=':
                    return market_value <= value
                elif comparator == '==':
                    return market_value == value
                elif comparator == '!=':
                    return market_value != value
            elif isinstance(market_value, str) and isinstance(value, str):
                if comparator == '==':
                    return market_value == value
                elif comparator == '!=':
                    return market_value != value
                elif comparator == 'contains':
                    return value in market_value
                elif comparator == 'not_contains':
                    return value not in market_value
            
            # 默认返回False
            return False
            
        except Exception as e:
            logger.error(f"Error comparing values: {str(e)}")
            return False
    
    def parse_natural_language_rule(self, natural_language: str) -> Dict[str, Any]:
        """解析自然语言规则（简化版实现）"""
        # 实际应用中应该使用NLP技术来解析自然语言规则
        # 这里提供一个简单的实现示例
        rule = {
            'conditions': [],
            'action': 'BUY',
            'symbol': 'AAPL',  # 默认股票代码
            'execution_strategy': 'MARKET',
            'order_type': 'MARKET'
        }
        
        # 简单关键词匹配
        natural_language = natural_language.lower()
        
        # 检查交易方向
        if 'sell' in natural_language or '卖出' in natural_language:
            rule['action'] = 'SELL'
        
        # 检查股票代码
        if 'aapl' in natural_language:
            rule['symbol'] = 'AAPL'
        elif 'msft' in natural_language:
            rule['symbol'] = 'MSFT'
        elif 'goog' in natural_language:
            rule['symbol'] = 'GOOG'
        
        # 检查条件
        if '突破' in natural_language and '均线' in natural_language:
            rule['conditions'].append({
                'field': 'price_above_ma20',
                'comparator': '==',
                'value': True
            })
        
        if '成交量放大' in natural_language:
            rule['conditions'].append({
                'field': 'volume_ratio',
                'comparator': '>',
                'value': 2.0
            })
        
        # 设置执行策略
        if 'vwap' in natural_language.lower():
            rule['execution_strategy'] = 'VWAP'
        elif 'twap' in natural_language.lower():
            rule['execution_strategy'] = 'TWAP'
        
        logger.info(f"Parsed natural language rule: '{natural_language}' -> {rule}")
        return rule

class AutoOrderEngine:
    """全自动条件单引擎"""
    def __init__(self, config=None):
        self.config = config or {
            'simulation_enabled': True,
            'risk_check_enabled': True,
            'max_rules': 100,
            'check_interval_ms': 100,  # 检查间隔（毫秒）
            'execution_timeout_seconds': 30,
            'debug_mode': False
        }
        
        # 初始化子模块
        self.rule_parser = RuleDSL()  # 策略规则解释器
        self.backtester = CloudSimulator()  # 云端仿真模块
        self.executor = SmartRouter()  # 智能订单路由
        self.position_sizer = PositionSizer()  # 动态仓位算法
        self.execution_strategy = ExecutionStrategy()  # 执行策略模块
        
        # 运行状态
        self.running = False
        self.last_check_time = 0
        
        # 执行统计
        self.stats = {
            'total_rules': 0,
            'rules_triggered': 0,
            'simulations_run': 0,
            'simulations_passed': 0,
            'orders_sent': 0,
            'orders_filled': 0,
            'orders_failed': 0,
            'execution_latency_ms': 0
        }
        
        logger.info("AutoOrderEngine initialized")
    
    def start(self):
        """启动引擎"""
        if self.running:
            logger.warning("Engine is already running")
            return False
        
        self.running = True
        logger.info("AutoOrderEngine started")
        
        # 启动执行流程
        self.execute_flow()
        
        return True
    
    def stop(self):
        """停止引擎"""
        if not self.running:
            logger.warning("Engine is not running")
            return False
        
        self.running = False
        logger.info("AutoOrderEngine stopped")
        
        # 清空运行状态
        self.last_check_time = 0
        
        return True
    
    def is_running(self) -> bool:
        """检查引擎是否运行中"""
        return self.running
    
    def execute_flow(self):
        """执行主流程"""
        logger.info("Starting execution flow")
        
        try:
            while self.running:
                # 记录开始时间
                cycle_start_time = time.time()
                
                # 获取实时行情
                market_data = self._get_real_time_feed()
                
                # 检查规则触发
                triggered_rules = self.rule_parser.check_rules(market_data)
                
                # 处理触发的规则
                for rule in triggered_rules:
                    self._process_triggered_rule(rule, market_data)
                
                # 更新统计
                self.stats['total_rules'] = len(self.rule_parser.get_rules())
                
                # 计算循环耗时
                cycle_time_ms = (time.time() - cycle_start_time) * 1000
                
                # 等待下一个检查周期
                wait_time_ms = max(0, self.config['check_interval_ms'] - cycle_time_ms)
                time.sleep(wait_time_ms / 1000)
                
        except Exception as e:
            logger.error(f"Error in execution flow: {str(e)}")
            self.running = False
    
    def _get_real_time_feed(self) -> Dict[str, Any]:
        """获取实时行情（模拟实现）"""
        # 实际应用中，这里应该从行情系统获取实时数据
        # 这里提供一个模拟实现
        current_time = time.time()
        
        # 模拟AAPL的实时行情
        market_data = {
            'timestamp': current_time,
            'aapl_price': 150.0 + (current_time % 100 - 50) * 0.01,  # 模拟价格波动
            'aapl_volume': 1000000 + int((current_time % 1000) * 1000),
            'aapl_bid': 149.98,
            'aapl_ask': 150.02,
            'aapl_volatility': 0.2,
            'aapl_ma5': 149.5,
            'aapl_ma10': 149.2,
            'aapl_ma20': 148.8,
            'price_above_ma20': True,
            'volume_ratio': 2.5,
            'market_status': 'OPEN'
        }
        
        # 模拟MSFT的实时行情
        market_data.update({
            'msft_price': 300.0 + ((current_time + 10) % 100 - 50) * 0.02,
            'msft_volume': 800000 + int(((current_time + 10) % 1000) * 800),
            'msft_bid': 299.95,
            'msft_ask': 300.05
        })
        
        # 模拟市场整体数据
        market_data.update({
            'sp500_index': 4500.0 + ((current_time + 20) % 100 - 50) * 0.5,
            'vix': 18.0 + ((current_time + 30) % 10 - 5) * 0.5,
            'market_volatility': 0.15,
            'liquidity_score': 0.85
        })
        
        return market_data
    
    def _process_triggered_rule(self, rule: Dict[str, Any], market_data: Dict[str, Any]):
        """处理触发的规则"""
        try:
            # 记录规则触发
            self.stats['rules_triggered'] += 1
            
            # 获取股票代码
            symbol = rule.get('symbol', '')
            
            if not symbol:
                logger.warning("No symbol specified in rule")
                return
            
            # 记录执行开始时间（用于计算延迟）
            execution_start_time = time.time()
            
            # 运行实时仿真验证（在触发前0.5秒进行微型回测验证）
            if self.config['simulation_enabled']:
                simulated_result = self.backtester.run(rule, market_data)
                self.stats['simulations_run'] += 1
                
                # 检查风险
                if self.config['risk_check_enabled'] and not simulated_result.pass_risk_check():
                    logger.warning(f"Rule {rule['rule_id']} failed risk check: {simulated_result.risk_score}")
                    return
                
                # 记录通过的仿真
                if self.config['risk_check_enabled']:
                    self.stats['simulations_passed'] += 1
            
            # 计算仓位大小
            position_size = self._calculate_position_size(rule, market_data)
            
            if position_size <= 0:
                logger.warning(f"Invalid position size calculated: {position_size}")
                return
            
            # 获取执行策略
            execution_strategy = rule.get('execution_strategy', 'MARKET')
            
            # 发送订单
            order_result = self.executor.send_order(
                symbol=symbol,
                qty=position_size,
                algo=execution_strategy,
                order_type=rule.get('order_type', 'MARKET'),
                side=rule.get('action', 'BUY'),
                price=market_data.get(f'{symbol.lower()}_price', 0.0),
                market_data=market_data
            )
            
            # 更新统计
            self.stats['orders_sent'] += 1
            
            if order_result.get('success', False):
                # 订单发送成功
                order_id = order_result.get('order_id')
                logger.info(f"Order sent successfully: {order_id}, symbol: {symbol}, qty: {position_size}")
                
                # 记录订单填充情况
                if order_result.get('status') == 'FILLED':
                    self.stats['orders_filled'] += 1
                
            else:
                # 订单发送失败
                self.stats['orders_failed'] += 1
                error_msg = order_result.get('error', 'Unknown error')
                logger.error(f"Failed to send order: {error_msg}")
            
            # 计算执行延迟
            execution_latency_ms = (time.time() - execution_start_time) * 1000
            
            # 更新平均执行延迟（使用指数加权移动平均）
            self.stats['execution_latency_ms'] = (
                self.stats['execution_latency_ms'] * 0.9 +
                execution_latency_ms * 0.1
            )
            
            # 检查执行延迟是否符合要求（≤100ms）
            if execution_latency_ms > 100:
                logger.warning(f"Execution latency exceeded 100ms: {execution_latency_ms}ms")
            
        except Exception as e:
            logger.error(f"Error processing rule {rule.get('rule_id')}: {str(e)}")
    
    def _calculate_position_size(self, rule: Dict[str, Any], market_data: Dict[str, Any]) -> int:
        """计算仓位大小"""
        try:
            # 获取股票代码
            symbol = rule.get('symbol', '')
            
            if not symbol:
                return 0
            
            # 准备信号信息
            signal_info = {
                'current_price': market_data.get(f'{symbol.lower()}_price', 0.0),
                'stop_loss_price': rule.get('stop_loss_price', 0.0),
                'direction': rule.get('action', 'BUY'),
                'volatility': market_data.get(f'{symbol.lower()}_volatility', 0.2),
                'win_rate': rule.get('win_rate', 0.5),
                'risk_reward_ratio': rule.get('risk_reward_ratio', 1.5)
            }
            
            # 如果规则中定义了固定仓位大小，则使用该大小
            if 'position_size' in rule:
                return rule['position_size']
            
            # 使用动态仓位算法计算仓位大小
            sizing_method_str = rule.get('sizing_method', 'RISK_PER_TRADE')
            
            try:
                # 转换为枚举类型
                sizing_method = SizingMethod[sizing_method_str]
            except KeyError:
                # 如果无效，使用默认值
                sizing_method = SizingMethod.RISK_PER_TRADE
                logger.warning(f"Invalid sizing method: {sizing_method_str}, using default: RISK_PER_TRADE")
            
            # 调用动态仓位算法计算仓位大小
            result = self.position_sizer.calculate_position_size(symbol, signal_info, sizing_method)
            
            if result.get('success', False):
                return result.get('position_size', 0)
            else:
                logger.error(f"Error calculating position size: {result.get('error')}")
                return 0
                
        except Exception as e:
            logger.error(f"Error calculating position size: {str(e)}")
            return 0
    
    def add_strategy_rule(self, rule_definition: Dict[str, Any]) -> int:
        """添加策略规则"""
        # 检查规则数量限制
        if len(self.rule_parser.get_rules()) >= self.config['max_rules']:
            logger.error(f"Maximum number of rules ({self.config['max_rules']}) reached")
            return -1
        
        # 添加规则
        rule_id = self.rule_parser.add_rule(rule_definition)
        
        # 更新统计
        self.stats['total_rules'] = len(self.rule_parser.get_rules())
        
        return rule_id
    
    def remove_strategy_rule(self, rule_id: int) -> bool:
        """移除策略规则"""
        result = self.rule_parser.remove_rule(rule_id)
        
        # 更新统计
        self.stats['total_rules'] = len(self.rule_parser.get_rules())
        
        return result
    
    def update_strategy_rule(self, rule_id: int, updated_definition: Dict[str, Any]) -> bool:
        """更新策略规则"""
        return self.rule_parser.update_rule(rule_id, updated_definition)
    
    def get_strategy_rules(self) -> List[Dict[str, Any]]:
        """获取所有策略规则"""
        return self.rule_parser.get_rules()
    
    def parse_natural_language_rule(self, natural_language: str) -> Dict[str, Any]:
        """解析自然语言规则"""
        return self.rule_parser.parse_natural_language_rule(natural_language)
    
    def get_stats(self) -> Dict[str, Any]:
        """获取统计信息"""
        return self.stats.copy()
    
    def reset_stats(self):
        """重置统计信息"""
        self.stats = {
            'total_rules': len(self.rule_parser.get_rules()),
            'rules_triggered': 0,
            'simulations_run': 0,
            'simulations_passed': 0,
            'orders_sent': 0,
            'orders_filled': 0,
            'orders_failed': 0,
            'execution_latency_ms': 0
        }
        
        logger.info("Statistics reset")
        return True
    
    def set_config(self, **kwargs):
        """设置引擎配置"""
        for key, value in kwargs.items():
            if key in self.config:
                self.config[key] = value
        
        logger.info(f"Engine configuration updated: {kwargs}")
        return self.config
    
    def get_order_history(self) -> List[Dict[str, Any]]:
        """获取订单历史"""
        return self.executor.get_order_history()
    
    def get_simulation_history(self) -> List[Dict[str, Any]]:
        """获取仿真历史"""
        return self.backtester.get_simulation_history()
    
    def cancel_all_orders(self) -> Dict[str, Any]:
        """取消所有订单"""
        return self.executor.cancel_all_orders()
    
    def cancel_order(self, order_id: str) -> Dict[str, Any]:
        """取消指定订单"""
        return self.executor.cancel_order(order_id)
    
    def pause_rule(self, rule_id: int) -> bool:
        """暂停指定规则"""
        # 获取规则
        rules = self.rule_parser.get_rules()
        
        for rule in rules:
            if rule['rule_id'] == rule_id:
                # 更新规则为禁用状态
                rule['disabled'] = True
                return self.rule_parser.update_rule(rule_id, rule)
        
        logger.warning(f"Rule not found for pause: {rule_id}")
        return False
    
    def resume_rule(self, rule_id: int) -> bool:
        """恢复指定规则"""
        # 获取规则
        rules = self.rule_parser.get_rules()
        
        for rule in rules:
            if rule['rule_id'] == rule_id:
                # 更新规则为启用状态
                rule['disabled'] = False
                return self.rule_parser.update_rule(rule_id, rule)
        
        logger.warning(f"Rule not found for resume: {rule_id}")
        return False

# 示例使用
if __name__ == "__main__":
    # 创建AutoOrderEngine实例
    engine = AutoOrderEngine()
    
    # 更新账户信息（用于仓位计算）
    engine.position_sizer.update_account_info({
        'equity': 100000.0,
        'available_funds': 80000.0
    })
    
    # 添加一个简单的策略规则
    rule_definition = {
        'symbol': 'AAPL',
        'action': 'BUY',
        'conditions': [
            {
                'field': 'price_above_ma20',
                'comparator': '==',
                'value': True
            },
            {
                'field': 'volume_ratio',
                'comparator': '>',
                'value': 2.0
            }
        ],
        'operator': 'ALL',
        'execution_strategy': 'VWAP',
        'order_type': 'MARKET',
        'sizing_method': 'RISK_PER_TRADE',
        'cooldown_seconds': 300  # 5分钟冷却时间
    }
    
    rule_id = engine.add_strategy_rule(rule_definition)
    print(f"Added rule with ID: {rule_id}")
    
    # 解析自然语言规则
    natural_language_rule = "如果AAPL突破20日均线且成交量放大2倍，则买入"
    parsed_rule = engine.parse_natural_language_rule(natural_language_rule)
    print(f"Parsed natural language rule: {parsed_rule}")
    
    # 启动引擎（注意：在实际运行中，这将进入无限循环）
    print("Starting engine... (will run for 5 seconds)")
    
    # 修改配置，只运行5秒
    engine.set_config(check_interval_ms=500, debug_mode=True)
    
    # 模拟运行5秒
    start_time = time.time()
    while time.time() - start_time < 5 and engine.running:
        # 在调试模式下，手动调用execute_flow的核心逻辑
        market_data = engine._get_real_time_feed()
        triggered_rules = engine.rule_parser.check_rules(market_data)
        
        for rule in triggered_rules:
            engine._process_triggered_rule(rule, market_data)
        
        time.sleep(0.5)
    
    # 停止引擎
    engine.stop()
    
    # 获取统计信息
    stats = engine.get_stats()
    print(f"Engine statistics: {stats}")
    
    # 获取订单历史
    order_history = engine.get_order_history()
    print(f"Order history count: {len(order_history)}")